/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nhadat.xml;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import nhadat.action.GetPDFAction;
import nhadat.xml.objecttype.report.Report;
import nhadat.xml.objecttype.report.TindangmoiType;
import nhadat.xml.objecttype.report.TindeleteType;
import nhadat.xml.objecttype.report.TinduocxemType;
import nhadat.xml.objecttype.report.TinupdateType;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.Fop;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
//import org.apache.fop.apps.FopFactory;
//import org.apache.fop.apps.MimeConstants;

/**
 *
 * @author Xe Bay
 */
public class XMLReportLogic {

    private String contextPath;

    public void setContextPath(String contextPath) {
        this.contextPath = contextPath;
    }

    public void recordTinMoiDang(TindangmoiType tin, String action) {
        Report report = readReportXML(contextPath + "report/report.xml");
        if (report == null) {
            report = new Report();
        }
        tin.setLoaitin(GetPDFAction.getUnsignedString(tin.getLoaitin()));
        report.getDsTinDangMoi().getTindangmoi().add(tin);
        createReportXML(report, contextPath + "report/report.xml");
    }

    public void recordTinDuocUpdate(TinupdateType tin, String action) {
        Report report = readReportXML(contextPath + "report/report.xml");
        if (report == null) {
            report = new Report();
        }
        tin.setLoaitin(GetPDFAction.getUnsignedString(tin.getLoaitin()));
        report.getDsTinDuocUpdate().getTinupdate().add(tin);
        createReportXML(report, contextPath + "report/report.xml");
    }

    public void recordTinDelete(TindeleteType tin, String action) {
        Report report = readReportXML(contextPath + "report/report.xml");
        if (report == null) {
            report = new Report();
        }
        
        report.getDsTinDelete().getTindelete().add(tin);
        createReportXML(report, contextPath + "report/report.xml");
    }

    public void recordTinDuocXem(TinduocxemType tin, String action) {
        Report report = readReportXML(contextPath + "report/report.xml");
        if (report == null) {
            report = new Report();
        }
        //boolean bInsertMoi = true;
        List<TinduocxemType> list = report.getDsTinDuocXem().getTinduocxem();
        if (list != null) {
            if (list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    TinduocxemType tempTin = (TinduocxemType) list.get(i);
                    if (tin.getMatindang().equals(tempTin.getMatindang())) {
                        int soluotxem = Integer.parseInt(tempTin.getSoluotxem()) + 1;
                        tin.setSoluotxem(soluotxem + "");
                        tin.setLoaitin(GetPDFAction.getUnsignedString(tin.getLoaitin()));
                        report.getDsTinDuocXem().getTinduocxem().remove(i);
                        //report.getDsTinDuocXem().getTinduocxem().add(tin);
                        //bInsertMoi = false;
                        break;
                    }
                }
            }
        }
        //if (bInsertMoi) {
        report.getDsTinDuocXem().getTinduocxem().add(tin);
        //}
        createReportXML(report, contextPath + "report/report.xml");
    }

    private void createReportXML(Report report, String outputPath) {
        if (report != null) {
            try {
                JAXBContext ctx = JAXBContext.newInstance(report.getClass());
                Marshaller mar = ctx.createMarshaller();
                mar.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
                mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                mar.marshal(report, new File(outputPath));
            } catch (JAXBException ex) {
                Logger.getLogger(XMLReportLogic.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private Report readReportXML(String inputXML) {
        File f = new File(inputXML);
        Report report = new Report();
        if (f.exists()) {
            try {
                JAXBContext jc = JAXBContext.newInstance("nhadat.xml.objecttype.report");
                Unmarshaller um = jc.createUnmarshaller();
                //JAXBElement jax = (JAXBElement) um.unmarshal(f);
                //report = (Report) jax.getValue();
                report = (Report) um.unmarshal(f);
                //System.out.println("");
            } catch (JAXBException ex) {
                Logger.getLogger(XMLReportLogic.class.getName()).log(Level.SEVERE, null, ex);
            } 
        }
        return report;
    }

    /*
     * Return String[2]:
     *   + Element 1: ten folder: format yyyy-MM-dd
     *   + Element 2: ten file: format yyyy-mm-dd-hhmmss
     */
    public String[] generateTheLocationOfReport() {
        String[] result = new String[2];

        Calendar currentDate = Calendar.getInstance();

        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd");
        result[0] = formatter1.format(currentDate.getTime());

        SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd-HHmmss");
        result[1] = formatter2.format(currentDate.getTime());

        return result;
    }

     public void methodTrAX(String xmlPath, String xslPath, String output){
//        try {
//            FopFactory fopFactory = FopFactory.newInstance();
//
//            OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(output)));
//            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
//
//            Source src = new StreamSource(new File(xmlPath));
//            Source xslt = new StreamSource(new File(xslPath));
//
//            TransformerFactory factory = TransformerFactory.newInstance();
//            Transformer trans = factory.newTransformer(xslt);
//
//            Result result = new SAXResult(fop.getDefaultHandler());
//
//            trans.transform(src, result);
//
//            out.close();
//        } catch (TransformerConfigurationException ex) {
//            ex.printStackTrace();
//        }catch(Exception ex){
//            ex.printStackTrace();
//        }
    }

    public void createReportXMLFO(String xmlPath, String xslPath, String foPath, String output) {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            StreamSource xsltFile = new StreamSource(xslPath);
            Transformer tran = tf.newTransformer(xsltFile);
            StreamSource xmlFile = new StreamSource(xmlPath);
            StreamResult foFile = new StreamResult(new FileOutputStream(foPath));
            tran.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            tran.transform(xmlFile, foFile);

            convertPDF(foPath,output);

        } catch(TransformerConfigurationException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void convertPDF(String foPath, String pdfPath){
        InputStream input = null;
        try {
            
            Driver driver = new Driver();
            org.apache.avalon.framework.logger.Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
            driver.setLogger(logger);
            org.apache.fop.messaging.MessageHandler.setScreenLogger(logger);
            driver.setRenderer(Driver.RENDER_PDF);
            File foFile = new File(foPath);
            File pdfFile = new File(pdfPath);
            input = new FileInputStream(foFile);
            driver.setInputSource(new InputSource(input));
            OutputStream output = new FileOutputStream(pdfFile);
            driver.setOutputStream(output);
            driver.run();
            output.flush();
            output.close();
        } catch (IOException ex) {
            Logger.getLogger(XMLReportLogic.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FOPException ex) {
            Logger.getLogger(XMLReportLogic.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                input.close();
            } catch (IOException ex) {
                Logger.getLogger(XMLReportLogic.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void createBLANK_ReportXML(String outputXML) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.newDocument();
//            doc.setXmlStandalone(false);
            Element dstindangFull = doc.createElement("report");
            dstindangFull.setTextContent("");
            doc.appendChild(dstindangFull);
            TransformerFactory tsf = TransformerFactory.newInstance();
            Transformer ts = tsf.newTransformer();
            ts.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            ts.setOutputProperty(OutputKeys.INDENT, "no");
            StreamResult rs = new StreamResult(new FileOutputStream(outputXML));
            DOMSource dom = new DOMSource(doc);
            ts.transform(dom, rs);
        } catch (TransformerException ex) {
            Logger.getLogger(XMLmanipulate.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(XMLmanipulate.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(XMLmanipulate.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
